﻿using System;
using System.Collections.Generic;
using LuaInterface;
using STTech.BytesIO.Core.Entity;
using STTech.BytesIO.Tcp;
using STTech.BytesIO.Tcp.Entity;
using Newtonsoft.Json;
using xframe_server;
using System.Threading;

namespace SocketUtil
{
    public class SocketServer
    {
        public Dictionary<string, TcpClient> dicClientSocket = new Dictionary<string, TcpClient>();
        private TcpServer tcpServer;


        private LuaFunction accceptCallback;
        private LuaFunction requestCallback;
        private LuaFunction disConnectCallback;
        private Thread thread;


        public Queue<ClientVO> waitingProtalListSend = new Queue<ClientVO>();
        public Queue<ClientVO> waitingProtalListReceive = new Queue<ClientVO>();
        private static ClientVO cacheReceive;

        public SocketServer()
        {
        }

        public void InitCallback(LuaFunction accceptCallback, LuaFunction requestCallback, LuaFunction disConnectCallback)
        {

            this.accceptCallback = accceptCallback;
            this.requestCallback = requestCallback;
            this.disConnectCallback = disConnectCallback;
        }

        public void Init(int port = 8885)
        {
            tcpServer = new TcpServer();
            tcpServer.Port = port;

            tcpServer.Started += ServerStart;
            tcpServer.Closed += ServerClose;
            tcpServer.ClientConnected += ClientConnected;
            tcpServer.ClientDisconnected += ClientDisconnected;

            tcpServer.ClientConnectionAcceptedHandle = (s, e) => {
                return true;
            };
            tcpServer.StartAsync();
        }



        public void SendAsync(string address, string json)
        {
            var client = this.GetClient(address);
            //var bytes = ProtoFormator.Format(protoID, data);
            client.SendAsync(json.GetBytes());
        }


        //通过地址获得tcp客户端
        public TcpClient GetClient(string address)
        {
            var client = this.dicClientSocket[address];
            return client;
        }

        ///回调///
        private void ClientDisconnected(object sender, ClientDisconnectedEventArgs e)
        {
            var address = e.Client.Host + ":" + e.Client.Port;
            Console.WriteLine($"C# {address}客户端断开了连接");
            if (this.dicClientSocket[address] != null)
            {
                this.dicClientSocket[address] = null;
            }
            if (this.disConnectCallback != null)
            {
                this.disConnectCallback.Call(address);
            }

        }

        private void ClientConnected(object sender, ClientConnectedEventArgs e)
        {
            var client = e.Client;
            var address = client.RemoteEndPoint.ToString();
            Console.WriteLine($"客户端连接 ==> {address}");
            dicClientSocket.Add(address, client);
            client.OnDataReceived += OnDataReceived;

            if (this.accceptCallback != null)
            {
                this.accceptCallback.Call(client, address);
            }
        }

        private void OnDataReceived(object sender, DataReceivedEventArgs e)
        {
            TcpClient tcpClient = (TcpClient)sender;
            //if (this.requestCallback != null)
            //{
            //    this.requestCallback.Call(e.Data.EncodeToString(), tcpClient.RemoteEndPoint.ToString());
            //}
            this.AddDataReceive(tcpClient.RemoteEndPoint.ToString(), e.Data.EncodeToString());
        }

        private void ServerStart(object sender, EventArgs e)
        {
            Console.WriteLine("开始监听");
        }

        private void ServerClose(object sender, EventArgs e)
        {
            Console.WriteLine("关闭服务器");
        }


        public void OpenThread()
        {
            if(this.thread == null)
            {
                this.thread = new Thread(HandlerWhile);
                this.thread.Start();
            }
        }

        private void HandlerWhile()
        {
            while (true)
            {
                if(waitingProtalListSend.Count > 0)
                {
                    //发送
                    var vo = waitingProtalListSend.Dequeue();
                    if (vo != null)
                    {
                        this.SendAsync(vo.address, vo.json);
                    }
                }

                if(waitingProtalListReceive.Count > 0)
                {

                    //接收
                    var vo2 = waitingProtalListReceive.Dequeue();
                    if (vo2 != null)
                    {
                        if (this.requestCallback != null)
                        {
                            cacheReceive = vo2;
                            this.requestCallback.Call();
                            cacheReceive = null;
                        }
                    }
                }

            }
        }


        public void AddDataSend(string address,string netStr)
        {
            waitingProtalListSend.Enqueue(new ClientVO(address,netStr));
        }

        public void AddDataReceive(string address, string netStr)
        {
            waitingProtalListReceive.Enqueue(new ClientVO(address, netStr));
        }


        public class ClientVO
        {
            public string address = "";
            public string json = "";

            public ClientVO(string address, string json)
            {
                this.address = address;
                this.json = json;
            }
        }
    }
}